/**
 * @作者 伟子涵
 * @微信公号 搬砖暗夜码农
 * @开源项目 $ https://gitee.com/zhouwei5208888
 * @我的博客 $ http://itzhouwei.com
 * @创建时间 2023/12/20  17:40
 */
package com.itzhouwei.minis.beans.factory;

import com.itzhouwei.minis.beans.BeanDefinition;
import com.itzhouwei.minis.beans.BeansException;
import com.itzhouwei.minis.beans.factory.support.BeanDefinitionRegistry;
import com.itzhouwei.minis.beans.factory.support.DefaultSingletonBeanRegistry;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @description:
 * @author：zw，微信：yingshengzw
 * @date: 2023/12/20  17:40
 * @Copyright： 公众号：搬砖暗夜码农 | 博客：https://itzhouwei.com - 沉淀、分享、成长，让自己和他人都能有所收获！
 */
@SuppressWarnings("all")
public class SimpleBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory, BeanDefinitionRegistry {
    private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    private List<String> beanDefinitionNames = new ArrayList<>();

    public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
        this.beanDefinitionMap.put(name, beanDefinition);
        this.beanDefinitionNames.add(name);
        if (!beanDefinition.isLazyInit()) {
            try {
                getBean(name);
            } catch (BeansException e) {
            }
        }
    }

    public void removeBeanDefinition(String name) {
        this.beanDefinitionMap.remove(name);
        this.beanDefinitionNames.remove(name);
        this.removeSingleton(name);
    }

    public BeanDefinition getBeanDefinition(String name) {
        return  this.beanDefinitionMap.get(name);
    }

    public boolean containsBeanDefinition(String name) {
        return this.beanDefinitionMap.containsKey(name);
    }

    /**
     * getBean，容器的核心方法
     * @param beanName 参数
     * @return
     * @throws BeansException
     */
    @Override
    public Object getBean(String beanName) throws BeansException {
        // 先尝试直接拿Bean实例
        Object singleton = this.getSingleton(beanName);
        // 如果此时还没有这个Bean的实例，则获取它的定义来创建实例
        if (singleton == null) {
            // 获取bean的定义
            BeanDefinition bd = (BeanDefinition) beanDefinitionMap.get(beanName);
            singleton=createBean(bd);
            // 新注册这个 bean 实例
            this.registerSingleton(beanName, singleton);
        }
        if (singleton == null) {
            throw new BeansException("bean is null.");
        }
        return singleton;
    }

    @Override
    public void registerBean(String beanName, Object obj) {
        this.registerSingleton(beanName, obj);
    }

    @Override
    public void registerBean(BeanDefinition beanDefinition) {
        this.beanDefinitionMap.put(beanDefinition.getId(), beanDefinition);
    }


    private Object createBean(BeanDefinition bd) {
        Object obj = null;
        try {
            obj = Class.forName(bd.getClassName()).newInstance();
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return obj;
    }

    @Override
    public Boolean containsBean(String beanName) {
        return containsBean(beanName);
    }

    public boolean isSingleton(String name) {
        return this.beanDefinitionMap.get(name).isSingleton();
    }


    public boolean isPrototype(String name) {
        return this.beanDefinitionMap.get(name).isPrototype();
    }

    public Class getType(String name) {
        return this.beanDefinitionMap.get(name).getClass();
    }
}